home *** CD-ROM | disk | FTP | other *** search
- /*
- * Menu module
- *
- * Copyright (c) Clever Bits and Bitgate Software 1993
- * All Rights Reserved.
- *
- * Handles menus and stuff
- *
- * [12.9.93 Karl A. 0ygard
- * not documented
- * [31.10.93] Karl A. 0ygard
- * - changed some code layout
- * [2.11.93] Karl A. 0ygard
- * domenu - changed some code layout
- * [7.11.93 - 3.4.94] Karl A. 0ygard and Ken Hollis
- * domenu - fixed bug to do with menus that go
- * outside screen on left side
- * DoDeskMenu - added for desktop menu management, and
- * side-drop down menus
- * - finally got the routines working for
- * side-drop down menus after two days
- * WMenuAttach - added for obvious reasons
- *
- * Karl: Added siderooted menu bars! Something we've both been
- * waiting for for a long time. Also added a desktop menu routine,
- * but it doesn't work with MultiTOS, or Geneva... We will probably
- * need to windowize this... It's easy enough to do anyway. We
- * also need to add these routines to the windowed routines...
- */
-
- #include <vdi.h>
- #include <stddef.h>
- #include <stdio.h>
- #include "winlib.h"
-
- #ifdef __TURBOC__
- #pragma warn -pia
- #endif
-
- #ifndef __MENU__
- #define __MENU__
- #endif
-
- MFDB screen; /* Screen mfdb */
-
- /*
- * Update menu box in window
- *
- * win = Window to update
- * x, y, w, h = Area to redraw
- */
- GLOBAL void WUpdateWindowMenu(WINDOW *win, int x, int y, int w, int h)
- {
- if (win->menubar) {
- GRECT own, temp;
-
- own.g_x = x;
- own.g_y = y;
- own.g_w = w;
- own.g_h = h;
-
- objc_offset(win->menubar, 1, &temp.g_x, &temp.g_y);
- temp.g_w = win->menubar[1].ob_width;
- temp.g_h = win->menubar[1].ob_height + 1;
-
- if (rc_intersect(&own, &temp)) {
- wind_update(BEG_UPDATE);
-
- WWindGet(win, WF_FIRSTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
- while (temp.g_w && temp.g_h) {
- if (rc_intersect(&temp, &own))
- objc_draw(win->menubar, 1, 2, temp.g_x, temp.g_y, temp.g_w, temp.g_h);
- WWindGet(win, WF_NEXTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
- }
-
- wind_update(END_UPDATE);
- }
- }
- }
-
- /*
- * Show or delete menubar
- *
- * me_btree = tree structure of menubar to show
- * me_bshow = if 0, deletes menubar
- * if 1, shows menubar
- *
- * (This call *should* be used when putting a menubar on the screen.
- * This is so that the program can always know what menubar is being
- * used and to provide full restoring of menus when an item has been
- * selected.)
- */
- GLOBAL int WMenuBar(OBJECT *me_btree, int me_bshow)
- {
- wl_menubar = me_bshow ? me_btree : 0;
-
- if (!me_bshow) {
- MenusShown = FALSE;
- return objc_draw(desktop, 0, 99, me_btree->ob_x, me_btree->ob_y, me_btree->ob_width, me_btree[1].ob_height);
- } else {
- MenusShown = TRUE;
- return objc_draw(me_btree, 0, 99, me_btree->ob_x, me_btree->ob_y, me_btree->ob_width, me_btree[1].ob_height);
- }
- }
-
-
- /*
- * Menu handling and stuff
- *
- * win = window in which menu is to be manipulated
- *
- * (This is one hell of a mess.)
- */
- GLOBAL void domenu(WINDOW *win)
- {
- GRECT work, mrct;
- OBJECT *dm_menubar;
- int mx, my, button, dummy;
- int message, pulldown = -1, oldpull = -1, menu, entry;
- int selection = -1;
- int x, y, w, h, tx, ty;
- void *ourbuffer;
-
- graf_mkstate(&mx, &my, &button, &dummy);
-
- wind_get(win->handle, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);
-
- wind_update(BEG_MCTRL);
- dm_menubar = win->menubar;
-
- do {
- graf_mkstate(&mx, &my, &button, &dummy);
-
- if (pulldown == -1) {
- if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1)
- if (!(dm_menubar[dummy].ob_state & DISABLED))
- pulldown = dummy;
- } else {
- if (oldpull != pulldown) { /* Changed pulldown? */
- menu = dm_menubar[dm_menubar[dm_menubar->ob_head].ob_next].ob_head;
- for (dummy = pulldown - 3; dummy > 0; dummy--)
- menu = dm_menubar[menu].ob_next;
-
- objc_offset(dm_menubar, menu, &x, &y);
- objc_offset(dm_menubar, pulldown, &tx, &ty);
- x--;
- y--;
- w = dm_menubar[menu].ob_width + 1;
- h = dm_menubar[menu].ob_height + 1;
-
- oldpull = pulldown;
-
- objc_change(dm_menubar, pulldown, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state | SELECTED, 0);
- objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
- mrct.g_w = dm_menubar[oldpull].ob_width;
- mrct.g_h = dm_menubar[oldpull].ob_height;
- if (rc_intersect(&mrct, &work))
- WUpdateWindowMenu(win, mrct.g_x, mrct.g_y, mrct.g_w, mrct.g_h);
-
- if ((tx = (x + w) - (desk.g_x + desk.g_w)) < 0)
- if (x < 8)
- tx = x - 8;
- else
- tx = 0;
- else
- tx += 8;
-
- if (((y + h) - (desk.g_y + desk.g_h)) < 0)
- ty = 0;
- else
- ty -= y + h;
-
- x -= tx;
- y += ty;
- dm_menubar[menu].ob_x -= tx;
- dm_menubar[menu].ob_y += ty;
-
- ourbuffer = scrsave(VDIhandle, x, y, x + w, y + h);
- objc_draw(dm_menubar, menu, 2, 0, 0, 16383, 16383);
- }
-
- if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1) /* Within a menu? */ {
- if (work.g_x + work.g_w > mx && !(dm_menubar[dummy].ob_state & DISABLED))
- pulldown = dummy; /* Menu within window and enabled? */
- } else /* Within pulldown */
- if ((entry = objc_find(dm_menubar, menu, 1, mx, my)) > menu) {
- EVENT event;
-
- event.ev_mflags = MU_BUTTON | MU_M1 | MU_M2;
- event.ev_mbclicks = 1;
- event.ev_bmask = 0x13;
- event.ev_mbstate = 0;
-
- objc_offset(dm_menubar, menu, &event.ev_mm2x, &event.ev_mm2y);
- event.ev_mm2width = dm_menubar[menu].ob_width;
- event.ev_mm2height = dm_menubar[menu].ob_height;
- event.ev_mm1flags = event.ev_mm2flags = 1;
-
- do {
- if (!(dm_menubar[entry].ob_state & DISABLED))
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state | SELECTED, 1);
-
- objc_offset(dm_menubar, entry, &event.ev_mm1x, &event.ev_mm1y);
- event.ev_mm1width = dm_menubar[entry].ob_width;
- event.ev_mm1height = dm_menubar[entry].ob_height;
-
- message = EvntMulti(&event);
-
- if (!(dm_menubar[entry].ob_state & DISABLED))
- if (message == MU_BUTTON) {
- selection = entry;
- dm_menubar[entry].ob_state &= ~SELECTED;
- } else
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
-
- if (message & MU_M1)
- entry = objc_find(dm_menubar, menu, 1, event.ev_mmox, event.ev_mmoy);
- } while (!(message & MU_M2) && !(message == MU_BUTTON));
- }
-
- if (oldpull != pulldown || !button || selection != -1) {
- scrrestore(ourbuffer);
-
- objc_change(dm_menubar, oldpull, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state & ~SELECTED, 0);
- objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
- mrct.g_w = dm_menubar[oldpull].ob_width;
- mrct.g_h = dm_menubar[oldpull].ob_height;
- if (rc_intersect(&mrct, &work))
- WUpdateWindowMenu(win, mrct.g_x, mrct.g_y, mrct.g_w, mrct.g_h);
- }
- }
- } while (button && selection == -1);
-
- no_click();
- wind_update(END_MCTRL);
-
- if (selection != -1) {
- int msg_buf[8] = {MN_SELECTED, 0, 0, 0, 0, 0, 0, 0};
-
- msg_buf[3] = pulldown;
- msg_buf[4] = selection;
-
- WCallWndDispatcher(win, msg_buf);
- }
- }
-
- /*
- * Menu handling and stuff
- *
- * win = window in which menu is to be manipulated
- *
- * (This is one hell of a mess.)
- */
- GLOBAL void DoDeskMenu(OBJECT *men)
- {
- GRECT mrct;
- OBJECT *dm_menubar;
- int mx, my, button, dummy;
- void *ourbuffer;
- int message, pulldown = -1, oldpull = -1, menu = -1, entry = -1;
- int selection = -1;
- int sideroot = 0, sideobj = 0;
- int x, y, w, h, tx, ty;
-
- dm_menubar = men;
-
- do {
- graf_mkstate(&mx, &my, &button, &dummy);
-
- if (pulldown == -1) {
- if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1)
- if (!(dm_menubar[dummy].ob_state & DISABLED))
- pulldown = dummy;
- } else {
- if (oldpull != pulldown) { /* Changed pulldown? */
- menu = dm_menubar[dm_menubar[dm_menubar->ob_head].ob_next].ob_head;
- for (dummy = pulldown - 3; dummy > 0; dummy--)
- menu = dm_menubar[menu].ob_next;
-
- objc_offset(dm_menubar, menu, &x, &y);
- objc_offset(dm_menubar, pulldown, &tx, &ty);
- x--;
- y--;
- w = dm_menubar[menu].ob_width + 1;
- h = dm_menubar[menu].ob_height + 1;
-
- oldpull = pulldown;
-
- objc_change(dm_menubar, pulldown, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state | SELECTED, 1);
- objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
- mrct.g_w = dm_menubar[oldpull].ob_width;
- mrct.g_h = dm_menubar[oldpull].ob_height;
-
- if ((tx = (x + w) - (desk.g_x + desk.g_w)) < 0)
- if (x < 8)
- tx = x - 8;
- else
- tx = 0;
- else
- tx += 8;
-
- if (((y + h) - (desk.g_y + desk.g_h)) < 0)
- ty = 0;
- else
- ty -= y + h;
-
- x -= tx;
- y += ty;
- dm_menubar[menu].ob_x -= tx;
- dm_menubar[menu].ob_y += ty;
-
- ourbuffer = scrsave(VDIhandle, x, y, x + w, y + h);
-
- objc_draw(dm_menubar, menu, 2, 0, 0, 16383, 16383);
- }
-
- if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1) /* Within a menu? */ {
- if (desk.g_x + desk.g_w > mx && !(dm_menubar[dummy].ob_state & DISABLED))
- pulldown = dummy; /* Menu within window and enabled? */
- } else /* Within pulldown */
- if ((entry = objc_find(dm_menubar, menu, 1, mx, my)) > menu) {
- EVENT event;
-
- event.ev_mflags = MU_BUTTON | MU_M1 | MU_M2;
- event.ev_mbclicks = 1;
- event.ev_bmask = 0x101;
- event.ev_mbstate = 1;
-
- objc_offset(dm_menubar, menu, &event.ev_mm2x, &event.ev_mm2y);
- event.ev_mm2width = dm_menubar[menu].ob_width;
- event.ev_mm2height = dm_menubar[menu].ob_height;
- event.ev_mm1flags = event.ev_mm2flags = 1;
-
- do {
- if (!(dm_menubar[entry].ob_state & DISABLED))
- if ((entry > 0) && !(dm_menubar[entry].ob_state & DRAW3D))
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state | SELECTED, 1);
-
- if (dm_menubar[entry].ob_flags & MENUSIDE) {
- int tempx, tempy, tempobj;
- OBJECT *p;
-
- tempobj = (dm_menubar[entry].ob_type >> 8);
- if (tempobj) {
- rsrc_gaddr(R_TREE, tempobj, &p);
-
- objc_offset(dm_menubar, menu, &tempx, &tempy);
-
- PMovePopupCoord(p, tempx + dm_menubar[menu].ob_width + dm_menubar[entry].ob_x, tempy + dm_menubar[entry].ob_y);
- PShowPopupDesk(p);
- sideobj = PDoPopupDeskMenu(p, &button);
- sideroot = tempobj;
-
- event.ev_mm1width = dm_menubar[entry].ob_width + p->ob_width;
- event.ev_mm1height = dm_menubar[entry].ob_height;
- }
- }
-
- objc_offset(dm_menubar, entry, &event.ev_mm1x, &event.ev_mm1y);
-
- if (!(dm_menubar[entry].ob_flags & MENUSIDE)) {
- event.ev_mm1width = dm_menubar[entry].ob_width;
- event.ev_mm1height = dm_menubar[entry].ob_height;
- }
-
- message = EvntMulti(&event);
-
- if (message & MU_M2)
- if (dm_menubar[entry].ob_flags & MENUSIDE) {
- int tempx, tempy, tempobj, xxx;
- OBJECT *p;
-
- graf_mkstate(&tempx, &tempy, &xxx, &xxx);
- tempobj = (dm_menubar[entry].ob_type >> 8);
- if (tempobj) {
- rsrc_gaddr(R_TREE, tempobj, &p);
- if ((dm_menubar[entry].ob_state & SELECTED) && (objc_find(p, 0, 99, tempx, tempy)!=-1)) {
- sideobj = PDoPopupDeskMenu(p, &button);
- sideroot = tempobj;
- message &= ~MU_M2;
- } else {
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
- PEndPopupDesk(p);
- sideobj = sideroot = 0;
- entry = objc_find(dm_menubar, menu, 1, event.ev_mmox, event.ev_mmoy);
- }
- }
- }
-
- if (!(dm_menubar[entry].ob_state & DISABLED))
- if (message == MU_BUTTON) {
- selection = entry;
- dm_menubar[entry].ob_state &= ~SELECTED;
- if (dm_menubar[entry].ob_flags & MENUSIDE) {
- int tempobj;
- OBJECT *p;
-
- tempobj = (dm_menubar[entry].ob_type >> 8);
- if (tempobj) {
- rsrc_gaddr(R_TREE, tempobj, &p);
- if (entry > 0)
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
- sideobj = sideroot = 0;
- PEndPopupDesk(p);
- }
- } else
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
- } else
- if (dm_menubar[entry].ob_flags & MENUSIDE) {
- int tempobj;
- OBJECT *p;
-
- tempobj = (dm_menubar[entry].ob_type >> 8);
- if (tempobj) {
- rsrc_gaddr(R_TREE, tempobj, &p);
- if (entry > 0)
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
- PEndPopupDesk(p);
- }
- } else
- if (entry > 0)
- objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
-
- if (button)
- message |= MU_BUTTON;
-
- if (message & MU_M1)
- entry = objc_find(dm_menubar, menu, 1, event.ev_mmox, event.ev_mmoy);
- } while (!(message & MU_M2) && !(message == MU_BUTTON));
-
- if (message == MU_BUTTON)
- button = TRUE;
- }
-
- if (oldpull != pulldown || button || message == MU_BUTTON || selection != -1) {
- scrrestore(ourbuffer);
-
- objc_change(dm_menubar, oldpull, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state & ~SELECTED, 1);
- objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
- mrct.g_w = dm_menubar[oldpull].ob_width;
- mrct.g_h = dm_menubar[oldpull].ob_height;
- }
-
- if (dm_menubar[entry].ob_flags & MENUSIDE) {
- int tempobj;
- OBJECT *p;
-
- tempobj = (dm_menubar[entry].ob_type >> 8);
- if (tempobj) {
- rsrc_gaddr(R_TREE, tempobj, &p);
- PEndPopupDesk(p);
- }
- }
- }
- } while (!button);
-
- if (pulldown) {
- int msg_buf[8] = {MN_SELECTED, 0, 0, 0, 0, 0, 0, 0};
-
- msg_buf[1] = Ap_ID;
- msg_buf[3] = pulldown;
- msg_buf[4] = entry;
- msg_buf[5] = sideroot;
- msg_buf[6] = sideobj;
-
- appl_write(Ap_ID, 16, msg_buf);
- }
- }
-
- /*
- * Attach a popup menu bar to a menu item
- * by Ken Hollis
- *
- * Simply stores the index to find whenever an item is selected
- * inside a menu with our menu routines. The index is stored in the
- * upper eight bits as an index within the object type. (What a
- * hack!)
- */
- GLOBAL void WMenuAttach(OBJECT *menubar, int menuitem, int popupobj, BOOL attach)
- {
- /* if (attach)
- menubar[menuitem].ob_type = menubar[menuitem].ob_type | (popupobj << 8);
- else
- menubar[menuitem].ob_type = menubar[menuitem].ob_type | (0 << 8); */
- }